import 'dart:async';
import 'package:life_milestones/controller/MS-global-user-controller.dart';
import 'package:life_milestones/util/MS-config-info-util.dart';
import 'package:dio/dio.dart';

import '../MS-global-url.dart';
class MSLogRequestKey{
  static const String MSLogData = "data";
  static const String MSLogType = "log_type";
  static const String MSLogSubtype = "subtype";
  static const String MSLogBehavior = "behavior";
  static const String MSLogDeviceId = "device-id";
  static const String MSLogAndroidId = "android_id";
  static const String MSLogUserId = "user_id";
  static const String MSLogPkg = "pkg";
  static const String MSLogChnId = "chn_id";
  static const String MSLogVer = "ver";
  static const String MSLogPlatform = "platform";
  static const String MSLogModel = "model";
  static const String MSLogPVer = "p_ver";
  static const String MSLogLanId = "lan_id";
  static const String MSLogSecId = "sec_id";
  static const String MSLogUtmSource = "utm_source";
  static const String MSLogAfAdgroupId = "af_adgroup_id";
  static const String MSLogAfAdset = "af_adset";
  static const String MSLogAfAdsetId = "af_adset_id";
  static const String MSLogAfStatus = "af_status";
  static const String MSLogAfAgency = "af_agency";
  static const String MSLogAfChannel = "af_channel";
  static const String MSLogAfCampaign = "campaign";
  static const String MSLogAfCampaignId = "campaign_id";
  static const String MSLogCountry = "country";
  static const String MSLogsysLan = "sys_lan";
}
enum MSLogEventType {
  globalBehavior('event', 'global_behavior', 'event'),
  clickEvent("event", "click", "event");
  final String logType;
  final String subType;
  final String behavior;
  const MSLogEventType(this.logType, this.subType, this.behavior);
}
class MSLogPages {
    static const String LoginPage = "launch";
    static const String QuickLogin = "quicklogin";
    static const String AppleLogin = "applelogin";
    static const String ReadTerms = "terms";
    static const String ReadPrivacy = "privacy";
    static const String LoginSuccess = "loginsuccess";
    static const String Home = "home";
    static const String MileStone = "milestone";
    static const String Mine = "mine";
    static const String Store = "purchase";
    static const String CreateOrder ="createorder";
    static const String Edit = "editavatar";
    static const String Logout = "logout";
    static const String DeleteAccount = "deleteaccount";
}

class MSLog {
 
  static const String _event = 'event';
  static const String _tm = 'tm';
  static const String _page = 'page';
  static const String _subPage = 'subPage';
  static const String _terPage = 'terPage';
  static const String _broadcasterId = 'broadcasterId';
  static const String _duration = 'duration';
  MSLog._();
  static void addEvent({
    String? page,
    String? subPage,
    String? terPage,
    String? broadcasterId,
  }) {
    var parameters = <String, dynamic>{};
    if (page != null) {
      parameters[_page] = page;
    }
    if (subPage != null) {
      parameters[_subPage] = subPage;
    }
    if (terPage != null) {
      parameters[_terPage] = terPage;
    }
    if (broadcasterId != null) {
      parameters[_broadcasterId] = broadcasterId;
    }
    parameters[_duration] = 0;
    parameters[_event] = 'pv';
    parameters[_tm] = DateTime.now().millisecondsSinceEpoch;
    MSLogManger().putLog(MSLogEventType.globalBehavior, parameters);
  }
}

class MSLogManger {
  static final MSLogManger _instance = MSLogManger._internal();
  factory MSLogManger() {
    return _instance;
  }
  static String launchId = '${DateTime.now().millisecondsSinceEpoch}${MSConfigInfoUtil().deviceId}';
  MSLogManger._internal();

  static const String tag = "LogManger";
  static const int max = 20;
  static int _serialId = 0;
  final List<Map<String, dynamic>> cacheList = [];
  bool _isWaitingForSend = false;

  void putLog(MSLogEventType logType, Map<String, dynamic>? event)async {
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> eventParameters = await composeEventData(
        logType.logType, logType.subType, logType.behavior, event);
    cacheList.insert(0, eventParameters);
    sendDelayed();
  }

  void sendDelayed() {
    if (_isWaitingForSend) {
      return;
    }
    _isWaitingForSend = true;
    Timer(const Duration(milliseconds: 2000), () {
      _isWaitingForSend = false;
      sendLog(false);
    });
  }

  void sendLog(bool forceUploadAll) {
    try {
      List<Map<String, dynamic>> sendList = [];
      if (cacheList.isEmpty) {
        return;
      } else if (cacheList.length >= max && !forceUploadAll) {
        sendList.addAll(cacheList.sublist(0, max));
        cacheList.removeRange(0, max);
      } else {
        sendList.addAll(cacheList);
        cacheList.clear();
      }
      _doUpload(sendList, true);
    } catch (e){}
  }

  void sendLogEventNow(MSLogEventType logType, Map<String, dynamic>? event) async{
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> eventParameters = await composeEventData(
        logType.logType, logType.subType, logType.behavior, event);
    List<Map<String, dynamic>> list = [];
    list.add(eventParameters);

    _doUpload(list, false);
  }

  Future<void> _doUpload(
      List<Map<String, dynamic>> sendList, bool isContinue) async {
    Dio(BaseOptions(baseUrl: MSGlobalUrl.trackHost)).post(MSGlobalUrl.trackPath,data: sendList).then((value){
    }).catchError((error)=>{});
  }

  Future<Map<String, dynamic>> composeEventData(String logType, String subType,
      String behavior, Map<String, dynamic>? event) async{
    String platform = '';
    Map<String, dynamic> eventParameters = {};
    eventParameters[MSLogRequestKey.MSLogData] = [event];
    eventParameters[MSLogRequestKey.MSLogType] = 'event';
    eventParameters[MSLogRequestKey.MSLogSubtype] = 'global_behavior';
    eventParameters[MSLogRequestKey.MSLogBehavior] = 'event';
    eventParameters[MSLogRequestKey.MSLogDeviceId] = MSConfigInfoUtil().deviceId;
    eventParameters[MSLogRequestKey.MSLogUserId] = MSGlobalUserController().user?.userId ?? "";
    eventParameters[MSLogRequestKey.MSLogPkg] = MSConfigInfoUtil().package ?? '';
    eventParameters[MSLogRequestKey.MSLogChnId] = '';
    eventParameters[MSLogRequestKey.MSLogVer] = MSConfigInfoUtil().version ?? '';
    eventParameters[MSLogRequestKey.MSLogPlatform] = platform;
    eventParameters[MSLogRequestKey.MSLogModel] = MSConfigInfoUtil().model;
    eventParameters[MSLogRequestKey.MSLogPVer] = MSConfigInfoUtil().buildNumber ?? '';
    eventParameters[MSLogRequestKey.MSLogLanId] = launchId;
    eventParameters[MSLogRequestKey.MSLogSecId] = _serialId++;
    eventParameters[MSLogRequestKey.MSLogsysLan] = MSGlobalUserController().lang ?? '';
    eventParameters[MSLogRequestKey.MSLogCountry] = MSGlobalUserController().user?.country ?? '';
    eventParameters["tm"] = DateTime.now().millisecondsSinceEpoch;
    return eventParameters;
  }
}